<?php
// Copyright 2019 Hackware SpA <human@hackware.cl>
// This file is part of "Hackware Web Services Payment" and licensed under
// the terms of the GNU Affero General Public License version 3, or (at your
// option) a later version. You should have received a copy of this license
// along with the software. If not, see <https://www.gnu.org/licenses/>.

namespace Hawese\Payment\Gateways;

use Hawese\Payment\Support\Http as HttpSupport;
use UnexpectedValueException;

class FlowRequestBuilder extends AbstractRequestBuilder
{
    const ENDPOINT = 'https://www.flow.cl/api';
    const TEST_ENDPOINT = 'https://sandbox.flow.cl/api';

    private $credentials;

    public function __construct(...$args)
    {
        parent::__construct(...$args);

        $this->credentials = (object) config('gateways.flow.credentials');
        $this->addDefaultParams();
    }

    protected function getEndpoint(): string
    {
        if (config('gateways.flow.test_mode')) {
            return self::TEST_ENDPOINT;
        }
        return self::ENDPOINT;
    }

    private function addDefaultParams(): void
    {
        $params = array_merge($this->getBodyOrQueryParams(), [
            'apiKey' => $this->credentials->apiKey
        ]);

        if ($this->method == 'GET') {
            $this->uri = (string) $this->buildUri()->withQuery(
                HttpSupport::buildUriQuery($params)
            );
            $this->uri .= '&s=' . $this->getSignature();
        } elseif ($this->method == 'POST') {
            $this->bodyParams = $params;
            $this->bodyParams['s'] = $this->getSignature();
        } else {
            throw new UnexpectedValueException(
                "Request method $this->method is unsuported.",
                2002
            );
        }
    }

    private function getSignature(): string
    {
        return hash_hmac(
            'sha256',
            $this->toSign(),
            $this->credentials->secretKey
        );
    }

    private function toSign(): string
    {
        $params = $this->getBodyOrQueryParams();
        ksort($params);

        if ($this->method == 'GET') {
            return HttpSupport::buildUriQuery($params);
        }

        // POST
        array_walk($params, function (&$item, $key) {
            $item = "$key=$item";
        });
        return implode('&', $params);
    }
}
